// filename:lib/list.h
// autor:jiang xinpeng
// time:2020.12.20
// copyright:(C) 2020-2050 by Jiang xinpeng,all right are reserved

#ifndef LIB_LIST_H
#define LIB_LIST_H

#include <stddef.h>

// define list struct
typedef struct list
{
    struct list *prior; // point prior node
    struct list *next;  // point next node
} list_t;

// get list node owner
#define list_owner(ptr, type, member) container_of(ptr, type, member)

// get first node owner,otherwise return NULL
#define list_first_owner(head, type, member) \
    (((head)->next != (head)) ? list_owner((head)->next, type, member) : NULL)

// get last node owner,otherwise return NULLd
#define list_last_owner(head, type, member) \
    (((head)->prior != (head)) ? list_owner((head)->prior, type, member) : NULL)

// get list next owner
#define list_next_owner(pos, member) \
    list_owner((pos)->member.next, typeof(*pos), member)

// get list pre owner
#define list_pre_owner(pos, member) \
    list_owner((pos)->member.prior, typeof(*pos), member)

// traversal all node from front to last
#define list_traversal_all_to_next(head, pos) \
    for (pos = (head)->next; pos != (head); pos = (pos)->next)

// traversal all node from last to front
#define list_traversal_all_to_pre(head, pos) \
    for (pos = (head)->prior; pos != head; pos = (pos)->prior)

// traversal all owner from front to last
#define list_traversal_all_owner_to_next(pos, head, member) \
    for (pos = list_first_owner((head), typeof(*pos), member); &(pos)->member != head; pos = list_next_owner(pos, member))

#define list_traversal_all_owner_to_next_safe(pos, next, head, member) \
    for (pos = list_first_owner((head), typeof(*pos), member), next = list_next_owner(pos, member); &(pos)->member != (head); pos = next, next = list_next_owner(pos, member))

// traversal all owner from last to front
#define list_traversal_all_own_to_pre(pos, head, member) \
    for (pos = list_last_owner((head), typeof(*pos), member); &(pos)->member != (head); pos = list_pre_owner(pos, member))

#define list_traversal_all_owner_to_pre_safe(pos, pre, head, member) \
    for (pos = list_last_owner((head), typeof(*pos), member), pre = list_pre_owner(pos, member); &(pos)->member != (head); pos = pre, pre = list_pre_owner(pos, member))

#define LIST_HEAD(name) list_t name = LIST_HEAD_INIT(name)
#define LIST_HEAD_INIT(name) \
    {                        \
        &(name), &(name)     \
    }

void list_init(struct list *list); // list init
int list_is_head(struct list *list);
void list_insert(struct list *new, struct list *pre, struct list *next); // add list
void list_del(struct list *del);
void list_del_init(struct list *del);

void list_add_head(struct list *new, struct list *head);
void list_add_before(struct list *new, struct list *old);
void list_add_after(struct list *new, struct list *old);
void list_add_tail(struct list *new, struct list *head);

void list_replace(struct list *old, struct list *new);
void list_replace_init(struct list *old, struct list *new);

int list_empty(struct list *head);
int list_is_last(struct list *node, struct list *head);
int list_is_first(struct list *node, struct list *head);

void list_move_after(struct list *node, struct list *head);
void list_move_befor(struct list *node, struct list *head);

int list_find(struct list *list, struct list *head);
int list_length(struct list *head);
#endif